home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cdrtools-1.10 / lib / fconv.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-07  |  5.1 KB  |  253 lines

  1. /* @(#)fconv.c    1.28 00/05/07 Copyright 1985 J. Schilling */
  2. /*
  3.  *    Convert floating point numbers to strings for format.c
  4.  *    Should rather use the MT-safe routines [efg]convert()
  5.  *
  6.  *    Copyright (c) 1985 J. Schilling
  7.  */
  8. /*
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2, or (at your option)
  12.  * any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; see the file COPYING.  If not, write to
  21.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23.  
  24. #include <mconfig.h>    /* <- may define NO_FLOATINGPOINT */
  25. #ifndef    NO_FLOATINGPOINT
  26.  
  27. #include <stdxlib.h>
  28. #include <standard.h>
  29. #include <strdefs.h>
  30. #include <schily.h>
  31.  
  32. #if    !defined(HAVE_STDLIB_H) || defined(HAVE_DTOA)
  33. extern    char    *ecvt __PR((double, int, int *, int *));
  34. extern    char    *fcvt __PR((double, int, int *, int *));
  35. #endif
  36.  
  37. #if    defined(HAVE_ISNAN) && defined(HAVE_ISINF)
  38. #define    FOUND_ISXX
  39. #endif
  40.  
  41. #include <math.h>
  42.  
  43. #if    defined(HAVE_IEEEFP_H) && !defined(FOUND_ISXX)
  44. /*
  45.  * SVR4
  46.  */
  47. #include <ieeefp.h>
  48. #define    isnan    isnand
  49. #define    isinf    !finite
  50. #define    FOUND_ISXX
  51. #endif
  52.  
  53. #if    defined(HAVE_FP_H)  && !defined(FOUND_ISXX)
  54. /*
  55.  * WAS:
  56.  * #if    defined(__osf__) || defined(_IBMR2) || defined(_AIX)
  57.  */
  58. #include <fp.h> 
  59. #ifndef    isnan
  60. #define    isnan    IS_NAN
  61. #endif
  62. #ifndef    isinf
  63. #define    isinf    !FINITE
  64. /*#define    isinf    IS_INF*/
  65. #endif
  66. #define    FOUND_ISXX
  67. #endif 
  68.  
  69. /*
  70.  * WAS:
  71.  * #if    defined(__hpux) || defined(VMS) || defined(_SCO_DS) || defined(__QNX__)
  72.  */
  73. #if    defined(__hpux)
  74. #undef    isnan
  75. #undef    isinf
  76. #endif
  77.  
  78. #if    !defined(isnan) && !defined(HAVE_ISNAN)
  79. #define    isnan(val)    (0)
  80. #endif
  81. #if    !defined(isinf) && !defined(HAVE_ISINF)
  82. #define    isinf(val)    (0)
  83. #endif
  84.  
  85. #if !defined(HAVE_ECVT) || !defined(HAVE_FCVT) || !defined(HAVE_GCVT)
  86. #include "cvt.c"
  87. #endif
  88.  
  89. static    char    _nan[] = "(NaN)";
  90. static    char    _inf[] = "(Infinity)";
  91.  
  92. static    int    _ferr __PR((char *, double));
  93.  
  94. #ifdef    abs
  95. #    undef    abs
  96. #endif
  97. #define    abs(i)    ((i) < 0 ? -(i) : (i))
  98.  
  99. EXPORT int
  100. ftoes(s, val, fieldwidth, ndigits)
  101.     register    char     *s;
  102.             double    val;
  103.     register    int    fieldwidth;
  104.     register    int    ndigits;
  105. {
  106.     register    char    *b;
  107.     register    char    *rs;
  108.     register    int    len;
  109.     register    int    rdecpt;
  110.             int     decpt;
  111.             int    sign;
  112.  
  113.     if ((len = _ferr(s, val)) > 0)
  114.         return len;
  115.     rs = s;
  116. #ifdef    V7_FLOATSTYLE
  117.     b = ecvt(val, ndigits, &decpt, &sign);
  118.     rdecpt = decpt;
  119. #else
  120.     b = ecvt(val, ndigits+1, &decpt, &sign);
  121.     rdecpt = decpt-1;
  122. #endif
  123.     len = ndigits + 6;            /* Punkt e +/- nnn */
  124.     if (sign)
  125.         len++;
  126.     if (fieldwidth > len)
  127.         while (fieldwidth-- > len)
  128.             *rs++ = ' ';
  129.     if (sign)
  130.         *rs++ = '-';
  131. #ifndef    V7_FLOATSTYLE
  132.     if (*b)
  133.         *rs++ = *b++;
  134. #endif
  135.     *rs++ = '.';
  136.     while (*b && ndigits-- > 0)
  137.         *rs++ = *b++;
  138.     *rs++ = 'e';
  139.     *rs++ = rdecpt >= 0 ? '+' : '-';
  140.     rdecpt = abs(rdecpt);
  141. #ifndef    V7_FLOATSTYLE
  142.     if (rdecpt >= 100)
  143. #endif
  144.     {
  145.         *rs++ = rdecpt / 100 + '0';
  146.         rdecpt %= 100;
  147.     }
  148.     *rs++ = rdecpt / 10 + '0';
  149.     *rs++ = rdecpt % 10 + '0';
  150.     *rs = '\0';
  151.     return rs - s;
  152. }
  153.  
  154. /*
  155.  * fcvt() from Cygwin32 is buggy.
  156.  */
  157. #if    !defined(HAVE_FCVT) && defined(HAVE_ECVT)
  158. #define    USE_ECVT
  159. #endif
  160.  
  161. EXPORT int
  162. ftofs(s, val, fieldwidth, ndigits)
  163.     register    char     *s;
  164.             double    val;
  165.     register    int    fieldwidth;
  166.     register    int    ndigits;
  167. {
  168.     register    char    *b;
  169.     register    char    *rs;
  170.     register    int    len;
  171.     register    int    rdecpt;
  172.             int     decpt;
  173.             int    sign;
  174.  
  175.     if ((len = _ferr(s, val)) > 0)
  176.         return len;
  177.     rs = s;
  178. #ifdef    USE_ECVT
  179.     /*
  180.      * Needed on systems with broken fcvt() implementation
  181.      * (e.g. Cygwin32)
  182.      */
  183.     b = ecvt(val, ndigits, &decpt, &sign);
  184.     /*
  185.      * The next call is needed to force higher precision.
  186.      */
  187.     if (decpt > 0)
  188.         b = ecvt(val, ndigits+decpt, &decpt, &sign);
  189. #else
  190.     b = fcvt(val, ndigits, &decpt, &sign);
  191. #endif
  192.     rdecpt = decpt;
  193.     len = rdecpt + ndigits + 1;
  194.     if (rdecpt < 0)
  195.         len -= rdecpt;
  196.     if (sign)
  197.         len++;
  198.     if (fieldwidth > len)
  199.         while (fieldwidth-- > len)
  200.             *rs++ = ' ';
  201.     if (sign)
  202.         *rs++ = '-';
  203.     if (rdecpt > 0) {
  204.         len = rdecpt;
  205.         while (*b && len-- > 0)
  206.             *rs++ = *b++;
  207. #ifdef    USE_ECVT
  208.         while (len-- > 0)
  209.             *rs++ = '0';
  210. #endif
  211.     }
  212. #ifndef    V7_FLOATSTYLE
  213.     else {
  214.         *rs++ = '0';
  215.     }
  216. #endif
  217.     *rs++ = '.';
  218.     if (rdecpt < 0) {
  219.         len = rdecpt;
  220.         while (len++ < 0 && ndigits-- > 0)
  221.             *rs++ = '0';
  222.     }
  223.     while (*b && ndigits-- > 0)
  224.         *rs++ = *b++;
  225. #ifdef    USE_ECVT
  226.     while (ndigits-- > 0)
  227.         *rs++ = '0';
  228. #endif
  229.     *rs = '\0';
  230.     return rs - s;
  231. }
  232.  
  233. LOCAL int
  234. _ferr(s, val)
  235.     char    *s;
  236.     double    val;
  237. {
  238.     if (isnan(val)){
  239.         strcpy(s, _nan);
  240.         return (sizeof (_nan) - 1);
  241.     }
  242.  
  243.     /*
  244.      * Check first for NaN because finite() will return 1 on Nan too.
  245.      */
  246.     if (isinf(val)){
  247.         strcpy(s, _inf);
  248.         return (sizeof (_inf) - 1);
  249.     }
  250.     return 0;
  251. }
  252. #endif    /* NO_FLOATINGPOINT */
  253.